package com.hyzx.qbasic.admin.domain.service.impl;

import com.github.pagehelper.PageInfo;
import com.hyzx.qbasic.admin.common.scheduling.CronTaskRegistrar;
import com.hyzx.qbasic.admin.common.scheduling.SchedulingRunnable;
import com.hyzx.qbasic.admin.common.util.OperationResUtils;
import com.hyzx.qbasic.admin.domain.repository.ISysJobRepository;
import com.hyzx.qbasic.admin.domain.service.ISysJobService;
import com.hyzx.qbasic.admin.model.enums.SysJobStatus;
import com.hyzx.qbasic.admin.model.po.SysJobPO;
import com.hyzx.qbasic.admin.model.vo.req.admin.*;
import com.hyzx.qbasic.admin.model.vo.res.BaseOperationRes;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * 服务实现类
 *
 * @author 黄江华
 * @since 2019-03-19
 */

@Service
public class SysJobServiceImpl implements ISysJobService, CommandLineRunner {

    private static final Logger logger = LoggerFactory.getLogger(SysJobServiceImpl.class);

    @Autowired
    private ISysJobRepository sysJobRepository;

    @Autowired
    private CronTaskRegistrar cronTaskRegistrar;

    @Override
    public void run(String... args) {
        // 初始加载数据库里状态为正常的定时任务
        List<SysJobPO> jobList = sysJobRepository.getSysJobListByStatus(SysJobStatus.NORMAL.ordinal());
        if (CollectionUtils.isNotEmpty(jobList)) {
            for (SysJobPO job : jobList) {
                addCronTask(job.getBeanName(), job.getMethodName(), job.getMethodParams(), job.getCronExpression());
            }

            logger.info("定时任务已加载完毕...");
        }
    }

    @Override
    public PageInfo<SysJobPO> getPagedSysJobList(GetSysJobListReq req) {
        PageInfo<SysJobPO> sysJobList = sysJobRepository.getPagedSysJobList(
                req.getPageNum(), req.getPageSize(), req.getBeanName());

        return sysJobList;
    }

    @Override
    public SysJobPO getSysJobInfoById(GetSysJobInfoReq req) {
        return sysJobRepository.getSysJobById(req.getJobId());
    }

    @Override
    public BaseOperationRes addSysJob(AddSysJobReq req) {
        SysJobPO sysJob = new SysJobPO();
        sysJob.setBeanName(req.getBeanName());
        sysJob.setMethodName(req.getMethodName());
        sysJob.setMethodParams(req.getMethodParams());
        sysJob.setCronExpression(req.getCronExpression());
        sysJob.setJobStatus(req.getJobStatus());
        sysJob.setRemark(req.getRemark());
        sysJob.setCreateTime(new Date());
        sysJob.setUpdateTime(new Date());

        boolean success = sysJobRepository.addSysJob(sysJob);
        if (!success)
            return OperationResUtils.fail("新增失败");
        else {
            if (req.getJobStatus().equals(SysJobStatus.NORMAL.ordinal()))
                addCronTask(req.getBeanName(), req.getMethodName(), req.getMethodParams(), req.getCronExpression());
        }

        return OperationResUtils.success();
    }

    @Override
    public BaseOperationRes editSysJob(EditSysJobReq req) {
        //检查记录是否存在
        SysJobPO existedSysJob = sysJobRepository.getSysJobById(req.getJobId());
        if (existedSysJob == null)
            return OperationResUtils.fail("记录不存在");

        SysJobPO sysJob = new SysJobPO();
        sysJob.setJobId(req.getJobId());
        sysJob.setBeanName(req.getBeanName());
        sysJob.setMethodName(req.getMethodName());
        sysJob.setMethodParams(req.getMethodParams());
        sysJob.setCronExpression(req.getCronExpression());
        sysJob.setJobStatus(req.getJobStatus());
        sysJob.setRemark(req.getRemark());
        sysJob.setUpdateTime(new Date());

        boolean success = sysJobRepository.editSysJob(sysJob);
        if (!success)
            return OperationResUtils.fail("编辑失败");
        else {
            //先移除再添加
            if (existedSysJob.getJobStatus().equals(SysJobStatus.NORMAL.ordinal()))
                removeCronTask(existedSysJob.getBeanName(), existedSysJob.getMethodName(), existedSysJob.getMethodParams());

            if (req.getJobStatus().equals(SysJobStatus.NORMAL.ordinal()))
                addCronTask(req.getBeanName(), req.getMethodName(), req.getMethodParams(), req.getCronExpression());
        }

        return OperationResUtils.success();
    }

    @Override
    public BaseOperationRes deleteSysJob(DeleteSysJobReq req) {
        boolean success = sysJobRepository.deleteSysJobByIds(req.getJobIdList());
        if (!success)
            return OperationResUtils.fail("删除失败");

        return OperationResUtils.success();
    }

    @Override
    public BaseOperationRes changeJobStatus(int jobId) {
        //检查记录是否存在
        SysJobPO existedSysJob = sysJobRepository.getSysJobById(jobId);
        if (existedSysJob == null)
            return OperationResUtils.fail("任务不存在");

        existedSysJob.setJobStatus(existedSysJob.getJobStatus() == 0 ? 1 : 0);
        existedSysJob.setUpdateTime(new Date());

        boolean success = sysJobRepository.editSysJob(existedSysJob);
        if (!success)
            return OperationResUtils.fail("切换任务运行状态失败");
        else {
            if (existedSysJob.getJobStatus().equals(SysJobStatus.NORMAL.ordinal())) {
                addCronTask(existedSysJob.getBeanName(), existedSysJob.getMethodName(), existedSysJob.getMethodParams(), existedSysJob.getCronExpression());
            } else {
                removeCronTask(existedSysJob.getBeanName(), existedSysJob.getMethodName(), existedSysJob.getMethodParams());
            }
        }

        return OperationResUtils.success();
    }

    private void addCronTask(String beanName, String methodName, String params, String cronExpression) {
        SchedulingRunnable task = new SchedulingRunnable(beanName, methodName, params);
        cronTaskRegistrar.addCronTask(task, cronExpression);
    }

    private void removeCronTask(String beanName, String methodName, String params) {
        SchedulingRunnable task = new SchedulingRunnable(beanName, methodName, params);
        cronTaskRegistrar.removeCronTask(task);
    }
}